home *** CD-ROM | disk | FTP | other *** search
/ Shareware Super Platinum 8 / Shareware Super Platinum 8.iso / mac / PROGTOOL / LIB211.ZIP;1 / STATS.PRG < prev    next >
Encoding:
Text File  |  1993-11-19  |  40.8 KB  |  1,011 lines

  1. *-----------------------------------------------------------------------
  2. *-- Program...: STATS.PRG
  3. *-- Programmer: Ken Mayer (CIS: 71333,1030) and 
  4. *--             Jay Parsons (CIS: 72662,1302)
  5. *-- Date......: 07/29/1993
  6. *-- Notes.....: Statistical Functions -- see README.TXT to include this 
  7. *--             library file in your system.
  8. *-----------------------------------------------------------------------
  9.  
  10. FUNCTION Samplevar
  11. *-----------------------------------------------------------------------
  12. *-- Programmer..: Jay Parsons (CIS: 72662,1302)
  13. *-- Date........: 04/13/1992
  14. *-- Notes.......: Finds sample variance of specified field of the 
  15. *--               current database, using CALCULATE command.
  16. *--               The CALCULATE command calculates the population 
  17. *--               variance, which is smaller by a factor of (n-1)/n.
  18. *-- Written for.: dBASE IV Version 1.5
  19. *-- Rev. History: Original function 1990.
  20. *--             : Modified to take optional parameter, 4/13/1992
  21. *-- Calls.......: None
  22. *-- Called by...: Any
  23. *-- Usage.......: Samplevar( <cField> [, <cClause> ] )
  24. *-- Example.....: ? Samplevar( "Balance", ".FOR..NOT.; 
  25. *--                                       isblank( Balance )" )
  26. *-- Returns.....: a numeric or float value, the sample variance, or 
  27. *--               .F. if it cannot be calculated. If any of the 
  28. *--               numeric items are floats, the result will be.
  29. *-- Parameters..: cField  = name of a numeric field of the current 
  30. *--                         database for which to calculate the sample
  31. *--                         variance
  32. *--             : cClause = optional, a FOR, WHILE, TO, etc. clause
  33. *-----------------------------------------------------------------------
  34.  
  35.    parameters cField, cCondition
  36.    private fVar, nCount, cCond
  37.    if pcount() = 2
  38.       m->cCond = " "+ m->cCondition
  39.    else
  40.       m->cCond = ""
  41.    endif
  42.    calculate var( &cField. ), CNT() TO m->fVar, m->nCount &cCond.
  43.  
  44. RETURN iif( m->nCount > 1, m->fVar * m->nCount / ( m->nCount - 1 ), ;
  45.            .F. )
  46. *-- Eof: Samplevar()
  47.  
  48. FUNCTION Stny
  49. *-----------------------------------------------------------------------
  50. *-- Programmer..: Jay Parsons (CIS: 72662,1302)
  51. *-- Date........: 11/13/1990
  52. *-- Notes.......: Returns value of the standard normal distribution 
  53. *--               function given a number of standard deviations from 
  54. *--               the mean. This function is not useful alone.  The 
  55. *--               standard normal distribution function is the familiar
  56. *--               bell-shaped curve scaled so its mean is at 0, each 
  57. *--               standard deviation is 1 and the total area under the 
  58. *--               curve is 1.  The function Stnarea calls on this 
  59. *--               function to calculate the approximate area (a fraction
  60. *--               equal to percent of the total) under the part of the 
  61. *--               curve lying betwen the mean and the given number of 
  62. *--               standard deviations.
  63. *-- Written for.: dBASE IV
  64. *-- Rev. History: 11/13/1990 -- Original Release
  65. *-- Calls       : None
  66. *-- Called by...: Any
  67. *-- Usage.......: Stny( <nDevs> )
  68. *-- Example.....: ? Stny( 1 )
  69. *-- Returns     : numeric value of the function.
  70. *-- Parameters..: nDevs = standard deviations from the mean
  71. *-----------------------------------------------------------------------
  72.  
  73.    parameters nDevs
  74.  
  75. RETURN exp( -m->nDevs * m->nDevs / 2 ) / sqrt( 2 * pi() )
  76. *-- EoF: Stny()
  77.  
  78. FUNCTION Stnarea
  79. *-----------------------------------------------------------------------
  80. *-- Programmer..: Jay Parsons (CIS: 72662,1302)
  81. *-- Date........: 11/13/1990
  82. *-- Notes.......: Area of the standard normal distribution function 
  83. *--               between mean and given number of standard deviations 
  84. *--               from the mean.
  85. *--             
  86. *--               What's it about?  Well, College Board scores 
  87. *--               (originally) were based on a normal distribution with
  88. *--               a mean of 500 and 100 points per standard deviation.
  89. *--               Knowing that a 650  score is 1.5 standard deviations 
  90. *--               from the 500 mean, we can calculate Stnarea( 1.5 ) 
  91. *--               as .4332.  This tells us that 43.32% of the scores 
  92. *--               lie between 650 and 500.  Since 50% lie below 500, 
  93. *--               a score of 650 beats 93.32% of the scores.
  94. *--             
  95. *--               The polynomial approximation used by this function is 
  96. *--               said to be accurate to .00001, 1/1000 of one percent.
  97. *--               Remember to SET DECIMALS appropriately to view 
  98. *--               results.
  99. *--             
  100. *-- Written for.: dBASE IV
  101. *-- Rev. History: 11/13/1990 -- Original Release
  102. *-- Calls       : Stny()            Function in STATS.PRG
  103. *-- Called by...: Any
  104. *-- Usage.......: Stnarea( <nDevs> )
  105. *-- Example.....: ? Stnarea( 1.5 )
  106. *-- Returns     : % of area between deviations given and the mean, 
  107. *--                 0<=a<.5.
  108. *-- Parameters..: nDevs = standard deviations from the mean
  109. *-----------------------------------------------------------------------
  110.  
  111.    parameters nDevs
  112.    private nX, nV
  113.  
  114.    m->nX = abs( m->nDevs )
  115.    m->nV =  1 / ( 1 + .33267 * m->nX )
  116.  
  117. RETURN .5 - Stny( m->nX ) * ( .4361836  * m->nV - .1201676 * m->nV *;
  118.         m->nV + .937298 * m->nV * m->nV * m->nV )
  119. *-- EoF: Stnarea()
  120.  
  121. FUNCTION Stnz
  122. *-----------------------------------------------------------------------
  123. *-- Programmer..: Jay Parsons (CIS: 72662,1302)
  124. *-- Date........: 11/13/1990
  125. *-- Notes.......: A lookup table to find the values of "z", standard
  126. *--               deviations, corresponding to the most common areas 
  127. *--               inside a given number of tails of the normal 
  128. *--               distribution function.
  129. *--             
  130. *--               Used in testing confidence intervals.  If a sample of
  131. *--               light bulbs from a shipment shows an average life of 
  132. *--               1150 hours, and the criterion for rejection of the 
  133. *--               shipment is 95% confidence that the average life of 
  134. *--               all bulbs is less than (a single tail) 1200 hours, 
  135. *--               the value 1.64485 returned by this function is 
  136. *--               necessary to determine whether to reject the shipment
  137. *--               or not.
  138. *--             
  139. *--               Values of "z" that are not found in the table can be 
  140. *--               found using Stndevs, below, but it is slow. 
  141. *-- Written for.: dBASE IV
  142. *-- Rev. History: 11/13/1990 -- Original Release
  143. *-- Calls       : None
  144. *-- Called by...: Any
  145. *-- Usage.......: Stnz( <nProb>, <nTails> )
  146. *-- Example.....: ? Stnz( .95, 1 )
  147. *-- Returns     : z = number of standard deviations from mean inside 
  148. *--                   which ( or to the side of which includes the 
  149. *--                   mean, if one tail) the given percentage of area 
  150. *--                   will fall.
  151. *--               Returns -1 if no entry in table.
  152. *-- Parameters..: nConf  = confidence desired, 0 < nConf < 1
  153. *--               nTails = 1 or 2 = number of tails of curve of interest
  154. *-----------------------------------------------------------------------
  155.  
  156.    parameters nConf, nTails
  157.  
  158.    if m->nTails # 1 .and. m->nTails # 2
  159.       RETURN -1
  160.    endif
  161.    do case
  162.       case m->nConf = .95
  163.          RETURN iif( m->nTails = 1, 1.64485, 1.96010 )
  164.       case m->nConf = .99
  165.          RETURN iif( m->nTails = 1, 2.32676, 2.57648 )
  166.       case m->nConf = .995
  167.          RETURN iif( m->nTails = 1, 2.57648, 2.80794 )
  168.       case m->nConf = .999
  169.          RETURN iif( m->nTails = 1, 3.09147, 3.29202 )
  170.       otherwise
  171.          RETURN -1
  172.    endcase
  173.  
  174. *-- EoF: Stnz()
  175.  
  176. FUNCTION Stndiff
  177. *-----------------------------------------------------------------------
  178. *-- Programmer..: Jay Parsons (CIS: 72662,1302)
  179. *-- Date........: 04/13/1992
  180. *-- Notes.......: Determines whether hypothesis that sample of a given 
  181. *--               mean is different from expected mean is justified.
  182. *--
  183. *--               if nPopstd, the standard deviation of the population, 
  184. *--               is not known and nSample, the sample size, is greater
  185. *--               than 30, the sample standard deviation may be used for
  186. *--               nPopstd.
  187. *--
  188. *--               This function assumes the population is large relative
  189. *--               to the sample or that the sampling is with 
  190. *--               replacement. if neither is true, the right side of the
  191. *--               expression in the later return line should be 
  192. *--               multiplied by:
  193. *--                     sqrt( ( nPop - nSample ) / ( nPop - 1 ) )
  194. *--               where nPop is the size of the population.
  195. *--
  196. *--               Do not use this with small samples, less than 20, 
  197. *--               because the standard normal distribution is not 
  198. *--               sufficiently accurate as an approximation of the 
  199. *--               distribution of sample means in such a case.  
  200. *--               See "Student's T-distribution" in a statistics text.
  201. *--
  202. *-- Written for.: dBASE IV Version 1.5
  203. *-- Rev. History: 04/13/1992 -- Original Release
  204. *-- Calls.......: Stnz()            Function in STATS.PRG
  205. *-- Called by...: Any
  206. *-- Usage.......: Stndiff( <m->nConf>, <nTails>, <nSample>,<nSampmean>,;
  207. *--                  <nPopmean>, <nPopstd> )
  208. *-- Example.....: ? Stndiff( .95, 1, 30, 1150, 1200, 20 )
  209. *-- Returns.....: .T. if hypothesis of difference is justified to degree 
  210. *--               of confidence specified, or .F.  Returns -1 if 
  211. *--               confidence is not one for which z can be looked up 
  212. *--               in Stnz().  if you need other confidence levels, 
  213. *--               run Stndevs() to find the z values for them and add 
  214. *--               them to the Stnz() table.
  215. *-- Parameters..: nConf     = confidence desired, 0 < m->nConf < 1
  216. *--               nTails    = 1 or 2 = number of tails of curve of 
  217. *--                           interest
  218. *--               nSample   = number of items in the sample
  219. *--               nSampmean = mean of the sample
  220. *--               nPopmean  = mean of the population (test standard 
  221. *--                           mean)
  222. *--               nPopstd   = standard deviation of population
  223. *-----------------------------------------------------------------------
  224.  
  225.    parameters nConf, nTails, nSample, nSampmean, ;
  226.               nPopmean, nPopstd
  227.    private nStd
  228.  
  229.    m->nStd = Stnz( m->nConf, m->nTails )
  230.    if m->nStd = -1
  231.       RETURN m->nStd
  232.    else
  233.       RETURN abs( m->nSampmean - m->nPopMean ) ;
  234.                  > m->nStd * m->nPopStd / sqrt( m->nSample )
  235.    endif
  236. *-- EoF: Stndiff()
  237.  
  238. FUNCTION Stndevs
  239. *-----------------------------------------------------------------------
  240. *-- Programmer..: Jay Parsons (CIS: 72662,1302)
  241. *-- Date........: 04/13/1992
  242. *-- Notes.......: Calculates "z", standard deviations, corresponding to 
  243. *--               any area of standard normal curve between mean and the
  244. *--               desired z. Much slower than Stnz().
  245. *-- Written for.: dBASE IV Version 1.5
  246. *-- Rev. History: Original function 1990.
  247. *--             : Conformed to Zeroin() 4/13/1992.
  248. *-- Calls.......: Zeroin()          Function in STATS.PRG 
  249. *-- Called by...: Any
  250. *-- Usage.......: Stndevs( <nArea> )
  251. *-- Example.....: ? Stndevs( .96 )
  252. *-- Returns.....: z, number of standard deviations from mean, or a 
  253. *--               negative number indicating failure to find a root..
  254. *-- Parameters..: nArea = area "left" of point of interest, 
  255. *--                        .5 < nArea < 1
  256. *-----------------------------------------------------------------------
  257.  
  258.    parameters nArea
  259.    private nTest, nFlag
  260.  
  261.    if m->nArea > .99999 .OR. m->nArea < .5
  262.       RETURN -1
  263.    endif
  264.    m->nFlag = 0
  265.    m->nTest = Zeroin( "TstmnArea", 0, 4.2, float(1/100000), 100, ;
  266.                          m->nFlag, m->nArea )
  267.  
  268. RETURN iif( m->nFlag < 3, m->nTest, -m->nFlag )
  269. *-- EoF: Stndevs()
  270.  
  271. FUNCTION Tstnarea
  272. *-----------------------------------------------------------------------
  273. *-- Programmer..: Jay Parsons (CIS: 72662,1302)
  274. *-- Date........: 11/13/1990
  275. *-- Notes.......: Translation function to convert area to left of point
  276. *--             : under standard normal curve to 0 for Zeroin().
  277. *-- Written for.: dBASE IV
  278. *-- Rev. History: 11/13/1990 -- Original Release
  279. *-- Calls.......: Stnarea()         Function in STATS.PRG
  280. *-- Called by...: Any
  281. *-- Usage.......: Tstnarea( <nDevs>, <nArea> )
  282. *-- Example.....: ? Tstnarea( 1.6,.96 )
  283. *-- Returns.....: positive or negative number corresponding to direction
  284. *--               to root where nArea = Stnarea
  285. *-- Parameters..: nDevs = trial number of standard deviations
  286. *--               nArea = area for which deviations are to be found
  287. *-----------------------------------------------------------------------
  288.  
  289.    parameters nDevs, nArea
  290.  
  291. RETURN Stnarea( m->nDevs ) +.5 - m->nArea
  292. *-- EoF: Tstnarea()
  293.  
  294. FUNCTION Zeroin
  295. *-----------------------------------------------------------------------
  296. *-- Programmer..: Tony Lima (CIS: 72331,3724) and 
  297. *--               Jay Parsons (CIS: 72662,1302)
  298. *-- Date........: 04/13/1992
  299. *-- Notes.......: Finds a zero of a continuous function.
  300. *--               In substance, what this function does is close in on a
  301. *--               solution to a function that cannot otherwise be 
  302. *--               solved. Assuming Y = f(X), if Y1 and Y2, the values of
  303. *--               the function for X1 and X2, have different signs, 
  304. *--               there must be at least one value of X between X1 and 
  305. *--               X2 for which Y = 0, if the function is continuous.  
  306. *--               This function closes in on such a value of X by a 
  307. *--               trial-and-error process.
  308. *--             
  309. *--               This function is very slow, so a maximum number of 
  310. *--               iterations is passed as a parameter.  if the number 
  311. *--               of iterations is exceeded, the function will fail to 
  312. *--               find a root.  if this occurs, pick different original 
  313. *--               "X" values, increase the number of iterations or 
  314. *--               increase the errors allowed.  Once an approximate 
  315. *--               root is found, you can use values of X close on 
  316. *--               either side and reduce the error allowed to find an
  317. *--               improved solution.  Also, of course, the signs of Y 
  318. *--               must be different for the starting X values for the 
  319. *--               function to proceed at all.
  320. *--             
  321. *--               NOTE ESPECIALLY - There is NO guarantee that a root 
  322. *--               returned by this function is the only one, or the most
  323. *--               meaningful. It depends on the function that this 
  324. *--               function calls, but if that function has several 
  325. *--               roots, any of them may be returned. This can easily 
  326. *--               happen with such called functions as net present value
  327. *--               where the cash flows alternate from positive to 
  328. *--               negative and back, and in many other "real life" 
  329. *--               cases. See the discussion of @IRR in the documentation
  330. *--               of a good spreadsheet program such as Quattro Pro for 
  331. *--               further information.
  332. *--             
  333. *--               The method used by this function is a "secant and 
  334. *--               bisect" search.  The "secant" is the line connecting 
  335. *--               two X,Y points on a graph using standard Cartesian 
  336. *--               coordinates. Where the secant crosses the X axis is 
  337. *--               the best guess for the value of X that will have 
  338. *--               Y = 0, and will be correct if the function is linear
  339. *--               between the two points.  The basic strategy is to 
  340. *--               calculate Y at that value of X, then keep the new X 
  341. *--               and that one of the old X values that had a Y-value 
  342. *--               of opposite sign, and reiterate to close in.
  343. *--             
  344. *--               if the function is a simple curve with most of the 
  345. *--               change in Y close to one of the X-values, as often 
  346. *--               occurs if the initial values of X are poorly chosen, 
  347. *--               repeated secants will do little to find a Y-value 
  348. *--               close to zero and will reduce the difference in 
  349. *--               X-values only slightly.  In this case the function 
  350. *--               shifts to choosing the new X halfway between the old
  351. *--               ones, bisecting the difference and always reducing 
  352. *--               the bracket by half, for a while.
  353. *--             
  354. *--               While this function finds a "zero", it may be used to
  355. *--               find an X corresponding to any other value of Y.  
  356. *--               Suppose the function of X is FUNCTION Blackbox( X ) 
  357. *--               and it is desired to find a value of X for which 
  358. *--               f(X) = 7.  The trick is to interpose a function 
  359. *--               between Zeroin() and Blackbox() that will return a 
  360. *--               0 to Zeroin() whenever Blackbox() returns 7.  
  361. *--               By calling that function, Zeroin() finds a value of
  362. *--               X for which Blackbox( X ) = 7, as required:
  363. *--                 Result = Zeroin("Temp", <other parameters omitted>)
  364. *--             
  365. *--                 FUNCTION Temp
  366. *--                 parameters nQ
  367. *--                 RETURN Blackbox( nQ ) - 7
  368. *-- Written for.: dBASE IV Version 1.5
  369. *-- Rev. History: Original function 1990.
  370. *--             : Modified to take optional parameters, 4/13/1992
  371. *-- Calls.......: The function whose name is first parameter.
  372. *--             : NPV()             Function in FINANCE.PRG
  373. *-- Called by...: Any
  374. *-- Usage.......: Zeroin( <cFunction>, <fX1>, <fX2>, <fAbserror>, ;
  375. *--             :  <nMaxiter>, <n_Flag> ;
  376. *--             :  [, xPass1 [, xPass2 [, xPass3 ] ] ] )
  377. *-- Example.....: ? Zeroin( "Npv", 0, 200, .000001, 200, n_Flag, 11 )
  378. *-- Returns.....: a float value representing a root, if n_Flag < 3.
  379. *-- Parameters..: cFunction = the name of the function to solve for a 
  380. *--                           root.
  381. *--               fX1       = one of the X-values between which the 
  382. *--                           root is sought.
  383. *--               fX2       = the second of these values.
  384. *--               Note: These MUST be chosen so the f( X ) values for 
  385. *--               the two of them have opposite signs (they must 
  386. *--               bracket the result).
  387. *--               fAbserror  = the absolute error allowed in the result.
  388. *--               nMaxiter   = the maximum number of times to iterate.
  389. *--               n_Flag     = an integer to signal success ( < 3 ) or 
  390. *--                            failure.
  391. *--               xPass1 . . . 3 = arguments to be passed through to 
  392. *--                                cFunction.
  393. *--               The parameter "n_Flag" should be passed as a variable 
  394. *--               so it may be accessed on return.  The limit of 9 
  395. *--               literal parameters may require passing others as 
  396. *--               variables.  The "xPass" parameters are optional and 
  397. *--               the fact there are three of them is arbitrary; they 
  398. *--               exist to hold whatever parameters may be needed by 
  399. *--               the function cFunction being called aside from the 
  400. *--               value of X for which it is being evaluated.  Add more 
  401. *--               and change the 3 "&cFunc." lines below if you need 
  402. *--               more.
  403. *-- Side effects: Uses and alters a global numeric variable, here called
  404. *--               "n_Flag", to report error conditions resulting in 
  405. *--               value returned being meaningless.  Possible n_Flag 
  406. *--               values are:
  407. *--                     1     success - root found within error allowed
  408. *--                     2     success - root was found exactly
  409. *--                     3     error   - function value not converging
  410. *--                     4     error   - original values do not bracket a
  411. *--                                     root
  412. *--                     5     error   - maximum iterations exceeded
  413. *-----------------------------------------------------------------------
  414.  
  415.    parameters cFunc, fNearx, fFarx, fAbserr, nMaxiter, ;
  416.               n_Flag, xPass1, xPass2, xPass3
  417.    private nSplits, fBracket, fFary, fNeary, nIters
  418.    private fMaxabs, fOldx, fOldy, fDiffx, fAbsdiff, fSecant
  419.  
  420.    store 0 to m->nSplits, m->nIters
  421.    m->fBracket = abs ( m->fNearX - m->fFarX )
  422.    m->fFarY = &cFunc.( m->fFarX, m->xPass1, m->xPass2, m->xPass3 )
  423.    m->fNearY = &cFunc.( m->fNearX, m->xPass1, m->xPass2, m->xPass3 )
  424.  
  425.    if sign( m->fNearY ) = sign( m->fFarY )
  426.       m->n_Flag = 4
  427.       RETURN float(0)
  428.    endif
  429.  
  430.    m->fMaxAbs = max( abs( m->fNearY ), abs( m->fFarY ) )
  431.    m->n_Flag = 0
  432.  
  433.    * Main iteration loop
  434.  
  435.    do while .t.
  436.  
  437.       if abs( m->fFarY ) < abs( m->fNearY )
  438.  
  439.          * Interchange m->fNearX and fFarx so that
  440.          * m->fNearX is closer to a solution--
  441.          * abs( m->fNearY ) <= abs( m->fFarY )
  442.  
  443.          m->fOldX  = m->fNearX
  444.          m->fOldY  = m->fNearY
  445.          m->fNearX = m->fFarX
  446.          m->fNearY = m->fFarY
  447.          m->fFarX  = m->fOldX
  448.          m->fFarY  = m->fOldY
  449.       endif
  450.  
  451.       m->fDiffX = m->fFarX - m->fNearX
  452.       m->fAbsDiff = abs( m->fDiffX )
  453.  
  454.       * Test whether interval is too small to continue
  455.  
  456.       if m->fAbsDiff <= 2 * m->fAbsErr
  457.          if abs( m->fNearY ) > m->fMaxAbs
  458.  
  459.             * Yes, but we are out of bounds
  460.  
  461.             m->n_Flag = 3
  462.             m->fNearX = float(0)
  463.          else
  464.  
  465.             * Yes, and we have a solution!
  466.  
  467.             m->n_Flag = 1
  468.          endif
  469.          exit
  470.       endif
  471.  
  472.       * Save the last approximation to x and y
  473.  
  474.       m->fOldX = m->fNearX
  475.       m->fOldY = m->fNearY
  476.  
  477.       * Check if reduction in the size of
  478.       * bracketing interval is satisfactory.
  479.       * if not, bisect until it is.
  480.  
  481.       m->nSplits = m->nSplits + 1
  482.       if m->nSplits >= 4
  483.          if 4 * m->fAbsDiff >= m->fBracket
  484.             m->fNearX = m->fNearX + m->fDiffX / 2
  485.          else
  486.             m->nSplits = 0
  487.             m->fBracket = m->fAbsDiff / 2
  488.  
  489.             * Calculate secant
  490.  
  491.             m->fSecant = ( m->fNearX - m->fFarX ) * m->fNearY ;
  492.                                / ( m->fFarY - m->fNearY )
  493.  
  494.             * But not less than error allowed
  495.  
  496.             if abs( m->fSecant ) < m->fAbsErr
  497.                m->fNearX = m->fNearX + m->fAbsErr * sign( m->fDiffX )
  498.             else
  499.                m->fNearX = m->fNearX + m->fSecant
  500.             endif
  501.          endif
  502.       endif
  503.  
  504.       * Evaluate the function at the new approximation
  505.  
  506.       m->fNearY = &cFunc.( m->fNearX, m->xPass1, m->xPass2, m->xPass3 )
  507.  
  508.       * if it's exactly zero, we win!  Run with it
  509.  
  510.       if m->fNearY = 0.00
  511.          m->n_Flag = 2
  512.          exit
  513.       endif
  514.  
  515.       * else adjust iteration count and quit if too
  516.       * many iterations with no solution
  517.  
  518.       m->nIters = m->nIters + 1
  519.       if m->nIters > m->nMaxIter
  520.          m->n_Flag = 5
  521.          m->fNearX = float( 0 )
  522.          exit
  523.       endif
  524.  
  525.       * And finally keep as the new m->fFarX that one
  526.       * of the previous approximations, m->fFarX and
  527.       * fOldx, at which the function has a sign opposite
  528.       * to that at the new approximation, fNearx.
  529.  
  530.       if sign( m->fNearY ) = sign( m->fFarY )
  531.          m->fFarX = m->fOldX
  532.          m->fFarY = m->fOldY
  533.       endif
  534.    enddo
  535.  
  536. RETURN m->fNearX
  537. *-- EoF: Zeroin()
  538.  
  539. FUNCTION Median
  540. *-----------------------------------------------------------------------
  541. *-- Programmer..: Oktay Amiry (Borland Technical Support)
  542. *-- Date........: 12/01/1992
  543. *-- Notes.......: Median refers to the middle value in a list; it is the 
  544. *--               halfway point from the lowest value to the highest.
  545. *--               This was published in TechNotes, December 1992 issue.
  546. *-- Written for.: dBASE IV, 1.5
  547. *-- Rev. History: 12/01/1992 -- Original Release
  548. *-- Calls.......: None
  549. *-- Called by...: Any
  550. *-- Usage.......: Median(<nField>)
  551. *-- Example.....: ?Median("SCORE")
  552. *-- Returns.....: Character value
  553. *-- Parameters..: nField = an indexed numeric field name in the current 
  554. *--                        database
  555. *-----------------------------------------------------------------------
  556.    parameters nField
  557.    private nCount, lEven,cLow,cHigh,cMed
  558.    
  559.    do case
  560.       case isblank(dbf())
  561.          RETURN "No database is in use"
  562.       case tagcount() = 0
  563.          RETURN "Specified file must be indexed"
  564.       case type(m->nField) # "N"
  565.          RETURN "Specified field must be numeric"
  566.       case upper(key()) # upper(m->nField)
  567.          m->nCount = 1
  568.          do while m->nCount <= tagcount()
  569.             if upper(key(m->nCount)) # upper(m->nField)
  570.                m->nCount = m->nCount + 1
  571.             else
  572.                set order to tag(m->nCount)
  573.                exit
  574.             endif
  575.          enddo
  576.          if upper(key(m->nCount)) # upper(m->nField)
  577.             RETURN "Specified field must be indexed"
  578.          endif
  579.    endcase
  580.    go top
  581.    m->lEven = mod(reccount(),2) = 0
  582.    if m->lEven
  583.       skip ((reccount()/2) -1)
  584.       m->cLow = ltrim(str(&nField.))
  585.       skip
  586.       m->cHigh = ltrim(str(&nField.))
  587.    else
  588.       skip int(reccount()/2)
  589.       m->cMed = ltrim(str(&nField.))
  590.    endif
  591.  
  592. RETURN iif(m->lEven,m->cLow+" TO "+m->cHigh,m->cMed)
  593. *-- EoF: Median()
  594.  
  595. FUNCTION Mode
  596. *-----------------------------------------------------------------------
  597. *-- Programmer..: Oktay Amiry (Borland Technical Support)
  598. *-- Date........: 12/01/1992
  599. *-- Notes.......: Used to determine the item which occurs most 
  600. *--               frequently in a list. 
  601. *--               Printed in TechNotes, December 1992.
  602. *-- Written for.: dBASE IV, 1.5
  603. *-- Rev. History: 12/01/1992 -- Original Release
  604. *-- Calls.......: None
  605. *-- Called by...: Any
  606. *-- Usage.......: Mode(<xField>)
  607. *-- Example.....: ?Mode("SEX")
  608. *-- Returns.....: The item that is the most common among those in that 
  609. *--               field.
  610. *-- Parameters..: xField = an indexed field (it must be indexed)
  611. *-----------------------------------------------------------------------
  612.  
  613.    parameters xField
  614.    private nCount,nMem,nOccur,nHigh,nName
  615.    
  616.    do case
  617.       case tagcount() = 0
  618.          RETURN "Specified file must be indexed"
  619.       case reccount() <= 1
  620.          RETURN "Invalid number of records for MODE()"
  621.       *case type(m->xField) # "N"
  622.          *RETURN "Specified field must be Numeric"
  623.    endcase
  624.    if upper(order()) # upper(m->xField)
  625.       RETURN "Specified field must be indexed"
  626.    endif
  627.    
  628.    go top
  629.    m->nHigh = 1
  630.    m->nCount = 0
  631.    scan
  632.       m->xCurrent = &xField.
  633.       m->xSame = &xField.
  634.       scan while m->xCurrent = m->xSame
  635.          m->xCurrent = &xField.
  636.          if m->xCurrent = m->xSame
  637.             m->nCount = m->nCount + 1
  638.          endif
  639.       endscan
  640.       if m->nCount > m->nHigh
  641.          m->nHigh = m->nCount
  642.          m->xReturn = m->xSame
  643.       else
  644.          if m->nCount = m->nHigh
  645.             m->xReturn = -1
  646.          endif
  647.       endif
  648.       m->nCount = 0
  649.    endscan
  650.  
  651. RETURN iif(m->nHigh = 1, -1, m->xReturn)
  652. *-- EoF: Mode()
  653.  
  654. FUNCTION Prcntl
  655. *-----------------------------------------------------------------------
  656. *-- Programmer..: Oktay Amira (Borland Technical Support)
  657. *-- Date........: 12/01/1992
  658. *-- Notes.......: Returns the percentile ranking of a number compared to
  659. *--               a list. Printed in TechNotes, December 1992.
  660. *-- Written for.: dBASE IV, 1.5
  661. *-- Rev. History: 12/01/1992
  662. *-- Calls.......: None
  663. *-- Called by...: Any
  664. *-- Usage.......: Prcntl(<nField>,<nrank>)
  665. *-- Example.....: ?Prcntl("SCORE",90)
  666. *-- Returns.....: numeric
  667. *-- Parameters..: nField = a numeric field in a database
  668. *--               nRank  = number to be ranked.
  669. *-----------------------------------------------------------------------
  670.  
  671.    parameters nField,nRank
  672.    private nField,nRank,nPercentile
  673.    
  674.    count to m->nPercentile for m->nRank > &nField.
  675.    
  676. RETURN (m->nPercentile * 100) / reccount()
  677. *-- EoF: Prcntl()
  678.  
  679. FUNCTION Range
  680. *-----------------------------------------------------------------------
  681. *-- Programmer..: Oktay Amira (Borland Technical Support)
  682. *-- Date........: 12/01/1992
  683. *-- Notes.......: Returns a number representing the difference between 
  684. *--               the highest and lowest numbers of a list.
  685. *--               Originally printed in TechNotes, Dec. 1992
  686. *-- Written for.: dBASE IV, 1.5
  687. *-- Rev. History: 12/01/1992 -- Original Release
  688. *-- Calls.......: None
  689. *-- Called by...: Any
  690. *-- Usage.......: Range(<nField>)
  691. *-- Example.....: ?Range("SCORE")
  692. *-- Returns.....: Numeric
  693. *-- Parameters..: nField = a numeric field in an open database
  694. *-----------------------------------------------------------------------
  695.  
  696.    parameters nField
  697.    private nHigh,nLow
  698.    
  699.    calculate max(&nField.) to m->nHigh, min(&nField.) to m->nLow
  700.  
  701. RETURN (m->nHigh - m->nLow)
  702. *-- EoF: Range()
  703.  
  704. FUNCTION RMS
  705. *-----------------------------------------------------------------------
  706. *-- Programmer..: Oktay Amira (Borland Technical Support)
  707. *-- Date........: 12/01/1992
  708. *-- Notes.......: Root-Mean-Square can be applied to any numeric list
  709. *--               (ordinal, interval, and ratio) to find the overall 
  710. *--               size of the numbers in the list, in lieu of their 
  711. *--               signs.
  712. *--               Printed in TechNotes, December 1992.
  713. *-- Written for.: dBASE IV, 1.5
  714. *-- Rev. History: 12/01/1992 -- Original Release
  715. *-- Calls.......: None
  716. *-- Called by...: Any
  717. *-- Usage.......: RMS(<nField>)
  718. *-- Example.....: ?RMS("SCORE")
  719. *-- Returns.....: numeric
  720. *-- Parameters..: nField = a numeric field
  721. *-----------------------------------------------------------------------
  722.  
  723.    parameters nField
  724.    private nTotal
  725.    
  726.    calculate sum(&nField. ^ 2) to m->nTotal
  727.  
  728. RETURN sqrt((m->nTotal/reccount()))
  729. *-- EoF: RMS()
  730.  
  731. FUNCTION SD
  732. *-----------------------------------------------------------------------
  733. *-- Programmer..: Oktay Amira (Borland Technical Support)
  734. *-- Date........: 12/01/1992
  735. *-- Notes.......: Standard Deviation -- similar to the dBASE STD 
  736. *--               function. The standard deviation shows how far away 
  737. *--               numbers on a list are from their average. The value 
  738. *--               yielded by standard deviation is in the same units as 
  739. *--               the numbers which are used to calculate the SD. The 
  740. *--               SD() function can take two forms: an unbiased (n-1)
  741. *--               method and the biased (n-method) form. The SD() 
  742. *--               function, by default, takes the biased form, which is
  743. *--               the standard deviation for a population based on the 
  744. *--               entire population. With the explicit second parameter
  745. *--               being "S", the SD() performs the unbiased method, 
  746. *--               which is the standard deviation for a population that 
  747. *--               is based on a sample. This latter method, which is 
  748. *--               also referred to as the SD+, is usually the value 
  749. *--               produced by statistical calculators and is frequently
  750. *--               higher than population-based SD.
  751. *--               Printed in TechNotes, December 1992.
  752. *-- Written for.: dBASE IV, 1.5
  753. *-- Rev. History: 12/01/1992 -- Original Release
  754. *-- Calls.......: None
  755. *-- Called by...: Any
  756. *-- Usage.......: SD(<nField>[,"S"])
  757. *-- Example.....: ?SD("SCORE","S")
  758. *-- Returns.....: numeric
  759. *-- Parameters..: nField = a numeric field
  760. *-----------------------------------------------------------------------
  761.  
  762.    parameters nField, cType
  763.    private nAverage, nEntry
  764.    
  765.    calculate avg(&nField. ^ 2) to m->nEntry, ;
  766.              avg(&nField.) to m->nAverage
  767.    m->nAverage = m->nAverage ^ 2
  768.  
  769. RETURN iif(type("CTYPE") = "C" .and. upper(cType) = "S",;
  770.            sqrt(m->nEntry-m->nAverage)/sqrt((reccount()-1)/reccount()),;
  771.            sqrt(m->nEntry-m->nAverage))
  772. *-- EoF: SD()
  773.  
  774. FUNCTION SU
  775. *-----------------------------------------------------------------------
  776. *-- Programmer..: Oktay Amira (Borland Technical Support)
  777. *-- Date........: 12/01/1992
  778. *-- Notes.......: Standard Units is a unit of measurement often referred
  779. *--               to in various statistical calculations. Suffice it to 
  780. *--               note that SU is an intrinsic way of looking at data, 
  781. *--               indicating whether a value is above or below the 
  782. *--               average. A positive SU indicates the value was above 
  783. *--               average, while a negative SU indicates a below average
  784. *--               value.
  785. *--               Printed in TechNotes, December 1992.
  786. *-- Written for.: dBASE IV, 1.5
  787. *-- Rev. History: 12/01/1992 -- Original Release
  788. *-- Calls.......: None
  789. *-- Called by...: Any
  790. *-- Usage.......: SU(<nField>,<nConvert>)
  791. *-- Example.....: ?RMS("SCORE",75)
  792. *-- Returns.....: numeric
  793. *-- Parameters..: nField   = a numeric field
  794. *--               nConvert = number to be converted
  795. *-----------------------------------------------------------------------
  796.  
  797.    parameters nField,nNum
  798.    private nAverage,nStandard
  799.    
  800.    calculate avg(&nField.) to m->nAverage, ;
  801.              std(&nField.) to m->nStandard
  802.  
  803. RETURN iif(m->nStandard # 0,(nNum-m->nAverage)/m->nStandard,0)
  804. *-- EoF: SU()
  805.  
  806. FUNCTION CoEf
  807. *-----------------------------------------------------------------------
  808. *-- Programmer..: Oktay Amira (Borland Technical Support)
  809. *-- Date........: 12/01/1992
  810. *-- Notes.......: Correlation CoEfficiant -- uses as parameters the 
  811. *--               field names of two numeric fields representing two 
  812. *--               data sets. Both of these fields must belong to one 
  813. *--               database. The value returned is always between 
  814. *--               +1 and -1.
  815. *--               Printed in TechNotes, December 1992.
  816. *-- Written for.: dBASE IV, 1.5
  817. *-- Rev. History: 12/01/1992 -- Original Release
  818. *-- Calls.......: None
  819. *-- Called by...: Any
  820. *-- Usage.......: CoEf(<nField1>,<nField2>)
  821. *-- Example.....: ?CoEf("SCORE","MIDTERM")
  822. *-- Returns.....: numeric
  823. *-- Parameters..: nField1  = a numeric field
  824. *--               nField2  = second numeric field
  825. *-----------------------------------------------------------------------
  826.  
  827.    parameters nField1, nField2
  828.    private nTotal, n1Avg, n1Std, n2Avg, n2Std
  829.    
  830.    m->nTotal = 0
  831.    calculate avg(&nField1.) to m->n1Avg,;
  832.              std(&nField1.) to m->n1Std,;
  833.              avg(&nField2.) to m->n2Avg,;
  834.              std(&nField2.) to m->n2Std
  835.    scan
  836.       m->nTotal - m->nTotal + (&nField1. * &nField2.)
  837.    endscan
  838.  
  839. RETURN ( (m->nTotal/reccount()) - (m->n1Avg * m->n2Avg) ) / ;
  840.          (m->n1Std * m->n2Std)
  841. *-- EoF: CoEf()
  842.  
  843. FUNCTION Choose
  844. *-----------------------------------------------------------------------
  845. *-- Programmer..: Oktay Amira (Borland Technical Support)
  846. *-- Date........: 12/01/1992
  847. *-- Notes.......: Returns the nth item in a list. The UDF assumes that 
  848. *--               items in the list are separated by commas.
  849. *--               Printed in TechNotes, December 1992.
  850. *-- Written for.: dBASE IV, 1.5
  851. *-- Rev. History: 12/01/1992 -- Original Release
  852. *-- Calls.......: None
  853. *-- Called by...: Any
  854. *-- Usage.......: Choose(<cList>,<nItem>[,<cDelimiter>])
  855. *-- Example.....: ?Choose("A,B,C",2)        or
  856. *--               ?Choose(TIME(),1,":")
  857. *-- Returns.....: Character
  858. *-- Parameters..: cList      = List of items, normally separated by 
  859. *--                            commas (see optional parameter to change
  860. *--                            delimiter)
  861. *--               nItem      = item position in list
  862. *--               cDelimiter = optional -- if other than a comma is used
  863. *--                            to separate items in the list, define it
  864. *--                            here.
  865. *-----------------------------------------------------------------------
  866.  
  867.    parameter cList, nItem, cDelimiter
  868.    
  869.    do case
  870.       case pcount() < 2
  871.          RETURN "Invalid number of parameters"
  872.       case type("m->cList") # "C"
  873.          RETURN "First parameter must be character"
  874.       case type("m->nItem") # "N"
  875.          RETURN "Second parameter must be numeric"
  876.       case type("m->cDelimiter") = "L" .and. m->cDelimiter
  877.          RETURN "Third parameter must be character or empty"
  878.       case type("m->cDelimiter") = "L" .and. .not. m->cDelimiter
  879.          m->cDelimiter = ","
  880.          if .not. m->cDelimiter $ m->cList
  881.             RETURN "Wrong or missing delimiters in parameter"
  882.          endif
  883.       case type("m->cDelimiter") = "C" .and. .not. ;
  884.              m->cDelimiter $ m->cList
  885.          RETURN "First parameter is missing specified delimiter"
  886.    endcase
  887.    
  888.    m->nCom = 1
  889.    m->nBegin = 1
  890.    m->nEnd = 1
  891.    do while m->nEnd <= len(trim(m->cList))
  892.       if substr(m->cList,m->nEnd,1) # m->cDelimiter
  893.          m->nEnd = m->nEnd + 1
  894.       else
  895.          if m->nCom # m->nItem
  896.             m->nCom = m->nCom + 1
  897.             m->nEnd = m->nEnd + 1
  898.             m->nBegin = m->nEnd
  899.          else
  900.             m->nEnd = m->nEnd - m->nBegin
  901.             exit
  902.          endif
  903.       endif
  904.    enddo
  905.  
  906. RETURN substr(m->cList,m->nBegin,m->nEnd)
  907. *-- EoF: Choose()
  908.  
  909. *-----------------------------------------------------------------------
  910. *-- The functions below are here by courtesy ... (to make life easier on
  911. *-- the poor programmer ...)
  912. *-----------------------------------------------------------------------
  913.  
  914. FUNCTION Npv
  915. *-----------------------------------------------------------------------
  916. *-- Programmer..: Tony Lima (CIS: 72331,3724) and 
  917. *--               Jay Parsons (CIS: 72662,1302)
  918. *-- Date........: 03/01/1992
  919. *-- Notes.......: Net present value of array aCashflow[ nPeriods ]
  920. *--               Calculates npv given assumed rate and # periods.
  921. *-- Written for.: dBASE IV, 1.1
  922. *-- Rev. History: 03/01/1992 -- Original Release
  923. *-- Calls.......: None
  924. *-- Called by...: Any
  925. *-- Usage.......: NPV(<nRate>,<nPeriods>)
  926. *-- Example.....: ? NPV( .06, 6 )
  927. *-- Returns.....: Float = value of the project at given rate
  928. *-- Parameters..: nRate    = Interest Rate
  929. *--               nPeriods = Number of Periods to calculate for
  930. *-- Other inputs: Requires the array aCashflow[ ] set up before calling.
  931. *--               Each of its elements [n] holds the cash flow at the
  932. *--               beginning of period n, with a negative amount 
  933. *--               indicating a cash outflow.  Elements of value 0 must 
  934. *--               be included for all periods with no cash flow, and 
  935. *--               all periods must be of equal length. If the project 
  936. *--               is expected to require an immediate outlay
  937. *--               of $6,000 and to return $2,000 at the end of each of 
  938. *--               the first five years thereafter, the array will be:
  939. *--                     aCashflow[1] = -6000
  940. *--                     aCashflow[2] =  2000
  941. *--                     aCashflow[3] =  2000
  942. *--                         * * *
  943. *--                     aCashflow[6] =  2000
  944. *--               Rewriting function to have array name passed as a 
  945. *--               parameter is possible, but will slow down execution to 
  946. *--               an extent that will be very noticeable if this 
  947. *--               function is being repeatedly executed, as by Zeroin()
  948. *--               to find an Internal Rate of Return.
  949. *-----------------------------------------------------------------------
  950.  
  951.    parameters nRate, nPeriods
  952.    private nDiscount, nFactor, nPeriod, nNpv
  953.  
  954.    m->nPeriod = 1
  955.    m->nNPV = aCashflow[ 1 ]
  956.    m->nDiscount = float( 1 )
  957.    m->nFactor = 1 / ( 1 + nRate )
  958.    do while m->nPeriod < m->nPeriods
  959.       m->nPeriod = m->nPeriod + 1
  960.       m->nDiscount = m->nDiscount * m->nFactor
  961.       m->nNPV = m->nNPV + aCashflow[ m->nPeriod ] * m->nDiscount
  962.    enddo
  963.    
  964. RETURN m->nNPV
  965. *-- EoF: Npv()
  966.  
  967. FUNCTION ArrayRows
  968. *-----------------------------------------------------------------------
  969. *-- Programmer..: Jay Parsons (CIS: 72662,1302)
  970. *-- Date........: 03/01/1992
  971. *-- Notes.......: Number of Rows in an array
  972. *-- Written for.: dBASE IV, 1.1
  973. *-- Rev. History: 03/01/1992 -- Original Release
  974. *-- Calls.......: None
  975. *-- Called by...: Any
  976. *-- Usage.......: ArrayRows("<aArray>")
  977. *-- Example.....: n = ArrayRows("aTest")
  978. *-- Returns.....: numeric
  979. *-- Parameters..: aArray      = Name of array 
  980. *-----------------------------------------------------------------------
  981.  
  982.    parameters aArray
  983.    private nHi, nLo, nTrial, nDims
  984.  
  985.    m->nLo = 1
  986.    m->nHi = 1170
  987.    if type( "&aArray.[ 1, 1 ]" ) = "U"
  988.       m->nDims = 1
  989.    else
  990.       m->nDims = 2
  991.    endif
  992.    do while .T.
  993.       m->nTrial = int( ( m->nHi + m->nLo ) / 2 )
  994.       if m->nHi < m->nLo
  995.          exit
  996.       endif
  997.       if m->nDims = 1 .and. type( "&aArray.[ m->nTrial ]" ) = "U" .or.;
  998.          m->nDims = 2 .and. type( "&aArray.[ m->nTrial, 1 ]" ) = "U"
  999.          m->nHi = m->nTrial - 1
  1000.       else
  1001.          m->nLo = m->nTrial + 1
  1002.       endif
  1003.    enddo
  1004.    
  1005. RETURN m->nTrial
  1006. *-- EoF: ArrayRows()
  1007.  
  1008. *-----------------------------------------------------------------------
  1009. *-- End of Program: STATS.PRG
  1010. *-----------------------------------------------------------------------
  1011.